/*
尽可能还原 Promise 中的每一个 API, 并通过注释的方式描述思路和原理.
*/
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(executor) {
    // 处理执行器中的错误
    try {
      executor(this._resolve, this._reject);
    } catch (error) {
      this._reject(error);
    }
  }
  _value = undefined;
  _reason = undefined;
  _status = PENDING;

  fulfillCallback = [];
  rejectCallback = [];

  // resolve方法在执行器中调用，更改promise对象的状态，调用then方法第一个回调函数，传递成功后的值
  _resolve = (value) => {
    if (this._status !== PENDING) return;
    this._value = value;
    this._status = FULFILLED;
    // 状态更改后，依次执行所有的回调
    while (this.fulfillCallback.length) {
      this.fulfillCallback.shift()();
    }
  };

  // reject方法在执行器中调用，更改promise对象的状态，调用then方法第二个回调函数，传递失败后的原因
  _reject = (reason) => {
    if (this._status !== PENDING) return;
    this._reason = reason;
    this._status = REJECTED;
    // 状态更改后，依次执行所有的回调
    while (this.rejectCallback.length) {
      this.rejectCallback.shift()();
    }
  };

  then = (fulfillCallback, rejectCallback) => {
    // then方法返回一个promise，多以才可以进行链式调用
    // 链式调用要注意：上一个then方法中回调函数的return值，会作为下一个then方法回调函数的入参；且如果return是普通值，则直接resolve；如果是return值是一个promise，则要根据其状态决定resolve或reject
    fulfillCallback =
      typeof fulfillCallback === "function"
        ? fulfillCallback
        : (value) => value;
    rejectCallback =
      typeof rejectCallback === "function"
        ? rejectCallback
        : (reason) => {
            throw reason;
          };
    let promise = new MyPromise((res, rej) => {
      if (this._status === FULFILLED) {
        // 处理成功时回调函数中的错误
        try {
          setTimeout(() => {
            const result = fulfillCallback(this._value);
            handlePromise(result, res, rej, promise);
          }, 0);
        } catch (error) {
          rej(error);
        }
      }
      if (this._status === REJECTED) {
        try {
          setTimeout(() => {
            const result = rejectCallback(this._reason);
            handlePromise(result, res, rej, promise);
          }, 0);
        } catch (error) {
          rej(error);
        }
      }
      // pending状态时，先把回调函数存起来。这里是promise异步的关键
      this.fulfillCallback.push(() => {
        try {
          setTimeout(() => {
            const result = fulfillCallback(this._value);
            handlePromise(result, res, rej, promise);
          }, 0);
        } catch (error) {
          rej(error);
        }
      });
      this.rejectCallback.push(() => {
        try {
          setTimeout(() => {
            const result = fulfillCallback(this._value);
            handlePromise(result, res, rej, promise);
          }, 0);
        } catch (error) {
          rej(error);
        }
      });
    });
    return promise;
  };

  // MyPromise的静态方法，如果传入promise，则直接返回；如果传入普通值，则转换为promise后返回
  static resolve = (value) => {
    if (value instanceof MyPromise) {
      return value;
    }

    return new MyPromise((res) => res(value));
  };

  static reject = (reason) => {
    return new MyPromise((res, rej) => rej(reason));
  };
}

function handlePromise(result, resolve, reject, promise) {
  // 如果then方法返回的promise与其回调函数返回的promise是同一个，则报错
  if (result === promise) {
    return reject(
      new TypeError("Chaining cycle detected for promise #<Promise>")
    );
  }
  if (result instanceof MyPromise) {
    // 如果then的回调函数返回值是promise
    result.then(resolve, reject);
  } else {
    // 如果then的回调函数返回值是普通值
    resolve(result);
  }
}

// ------------------------测试----------------------------------------

const pro = new MyPromise((res, rej) => {
  setTimeout(() => {
    res("success");
    // rej("fali");
  }, 1000);
});

const pro1 = new MyPromise((res, rej) => {
  setTimeout(() => {
    res("success111");
  }, 2000);
});

const p1 = pro
  .then((val) => {
    console.log(val);
    return pro1;
  })
  .then((val) => {
    console.log(val);
    return 100;
  })
  .then((val) => {
    console.log(val);
  });

